package com.hitomi.refresh.view;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.DragInfo;
import ohos.app.Context;

/**
 * Created by Hitomis on 2016/3/2.
 */
public class FunGameRefreshView extends DirectionalLayout implements Component.LayoutRefreshedListener {
    /**
     * 下拉状态
     */
    public static final int STATUS_PULL_TO_REFRESH = 0;

    /**
     * 释放准备刷新状态
     */
    public static final int STATUS_RELEASE_TO_REFRESH = 1;

    /**
     * 正在刷新状态
     */
    public static final int STATUS_REFRESHING = 2;

    /**
     * 释放后，又按住玩游戏状态
     */
    public static final int STATUS_AGAIN_DOWN = 3;

    /**
     * 刷新完成状态
     */
    public static final int STATUS_REFRESH_FINISHED = 4;

    /**
     * 下拉拖动的黏性比率
     */
    private static final float STICK_RATIO = .65f;

    /**
     * 下拉刷新的回调接口
     */
    private FunGameRefreshListener mListener;

    /**
     * 下拉头的View
     */
    private FunGameHeader header;


    /**
     * 下拉控件布局参数
     */
    private ComponentContainer.LayoutConfig headerLayoutParams;

    /**
     * 下拉控件高度
     */
    private int hideHeaderHeight;

    /**
     * 当前状态
     */
    private int currentStatus = STATUS_REFRESH_FINISHED;

    /**
     * 手指按下时屏幕纵坐标
     */
    private float preDownY;


    /**
     * 刷新子线程任务是否执行完毕
     */
    private boolean isExecComplete;

    private int tempHeaderTopMargin;

    public FunGameRefreshView(Context context) {
        this(context, null);
    }

    public FunGameRefreshView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public FunGameRefreshView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setOrientation(VERTICAL);
        initView(context, attrSet);
    }

    private void initView(Context context, AttrSet attrs) {
        header = new FunGameHeader(context, attrs);
        addComponent(header, 0);
        setLayoutRefreshedListener(this);
    }


    @Override
    public void onRefreshed(Component component) {
        if (getChildCount() > 2) {
            throw new RuntimeException("FunGameRefreshView can only contain one Component");
        }
        hideHeaderHeight = -header.getHeight();
        headerLayoutParams = header.getLayoutConfig();
        headerLayoutParams.setMarginTop(hideHeaderHeight);
        header.setLayoutConfig(headerLayoutParams);
        setDraggedListener(1, draggedListener);
        setLayoutRefreshedListener(null);
    }

    private DraggedListener draggedListener = new DraggedListener() {
        @Override
        public void onDragDown(Component component, DragInfo dragInfo) {
        }

        @Override
        public void onDragStart(Component component, DragInfo dragInfo) {
            preDownY = dragInfo.startPoint.getPointYToInt();
            if (currentStatus == STATUS_REFRESHING) { // 表示释放后处于刷新状态时候，又按住了
                currentStatus = STATUS_AGAIN_DOWN;
                setHeaderTopMarign(0);
            }
        }

        @Override
        public void onDragUpdate(Component component, DragInfo dragInfo) {
            float currY = dragInfo.updatePoint.getPointYToInt();
            float distance = currY - preDownY;
            float offsetY = distance * STICK_RATIO;
            if (currentStatus == STATUS_AGAIN_DOWN) {
                header.moveRacket(offsetY);
                setHeaderTopMarign((int) (offsetY));
            } else {
                if (distance <= 0 && headerLayoutParams.getMarginTop() <= hideHeaderHeight) {
                    return;
                }
                if (headerLayoutParams.getMarginTop() > 0) { // 头部全部被下拉出来的时候状态转换为释放刷新
                    currentStatus = STATUS_RELEASE_TO_REFRESH;
                } else {
                    currentStatus = STATUS_PULL_TO_REFRESH;
                }
                // 通过偏移下拉头的topMargin值，来实现下拉效果
                setHeaderTopMarign((int) (offsetY + hideHeaderHeight));
            }
        }

        @Override
        public void onDragEnd(Component component, DragInfo dragInfo) {
            if (currentStatus == STATUS_AGAIN_DOWN) {
                currentStatus = STATUS_REFRESHING;
                if (isExecComplete) {
                    rollbackHeader(false);
                } else {
                    rollBack2Header(false);
                }
            } else {
                if (currentStatus == STATUS_PULL_TO_REFRESH) {
                    rollbackHeader(false);
                }
                if (currentStatus == STATUS_RELEASE_TO_REFRESH) {
                    rollBack2Header(true);
                }
            }
        }

        @Override
        public void onDragCancel(Component component, DragInfo dragInfo) {
        }
    };


    /**
     * 给header设置topMargin参数
     *
     * @param margin TopMarign
     */
    private void setHeaderTopMarign(int margin) {
        headerLayoutParams.setMarginTop(margin);
        header.setLayoutConfig(headerLayoutParams);
    }


    // 回滚到头部刷新控件的高度，并触发后台刷新任务
    private void rollBack2Header(boolean isRefresh) {
        AnimatorValue rbToHeaderAnimator = new AnimatorValue();
        long duration = (long) (headerLayoutParams.getMarginTop() * 1.1f) >= 0 ?
                (long) (headerLayoutParams.getMarginTop() * 1.1f) : 0;
        rbToHeaderAnimator.setDuration(duration);
        rbToHeaderAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        int topMargin = headerLayoutParams.getMarginTop();
        rbToHeaderAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                int marginValue = (int) (topMargin * (1 - v));
                setHeaderTopMarign(marginValue);
            }
        });
        if (isRefresh) {
            rbToHeaderAnimator.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                    currentStatus = STATUS_REFRESHING;
                    header.postStart();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            if (mListener != null) {
                                final long minTimes = 1500;
                                long startTimes = System.currentTimeMillis();
                                mListener.onPullRefreshing();
                                long diffTimes = System.currentTimeMillis() - startTimes;
                                if (diffTimes < minTimes) {
                                    try {
                                        Thread.sleep(minTimes - diffTimes);
                                    } catch (InterruptedException e) {
                                    }
                                }
                                mContext.getUITaskDispatcher().asyncDispatch(new Runnable() {
                                    @Override
                                    public void run() {
                                        if (mListener != null) {
                                            mListener.onRefreshComplete();
                                        }
                                        finishRefreshing();
                                    }
                                });
                            }
                        }
                    }).start();
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            });
        }
        header.back2StartPoint(duration);
        rbToHeaderAnimator.start();
    }

    // 回滚下拉刷新头部控件
    private void rollbackHeader(boolean isDelay) {
        tempHeaderTopMargin = headerLayoutParams.getMarginTop();
        AnimatorValue rbAnimator = new AnimatorValue();
        rbAnimator.setDuration(300);
        rbAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        rbAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                int marginValue = (int) ((header.getHeight() + tempHeaderTopMargin) * v);
                setHeaderTopMarign(-marginValue + tempHeaderTopMargin);
            }
        });
        rbAnimator.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
                if (currentStatus == STATUS_PULL_TO_REFRESH || currentStatus == STATUS_REFRESH_FINISHED) {
                    currentStatus = STATUS_REFRESH_FINISHED;
                    return;
                }
                currentStatus = STATUS_REFRESH_FINISHED;
                isExecComplete = false;
                header.postEnd();
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        if (isDelay) {
            rbAnimator.setDelay(500);
        }
        rbAnimator.start();
    }

    /**
     * 给下拉刷新控件注册一个监听器。
     *
     * @param listener 监听器的实现。
     */
    public void setOnRefreshListener(FunGameRefreshListener listener) {
        mListener = listener;
    }

    /**
     * 当所有的刷新逻辑完成后，记录调用一下，否则将一直处于正在刷新状态。
     */
    public void finishRefreshing() {
        header.postComplete();
        isExecComplete = true;
        if (currentStatus != STATUS_AGAIN_DOWN) {
            rollbackHeader(true);
        }
    }

    /**
     * 设置加载开始文字
     *
     * @param loadingText 加载文字
     */
    public void setLoadingText(String loadingText) {
        if (isEmptyByText(loadingText)) {
            return;
        }
        header.setHeaderLodingStr(loadingText);
    }

    /**
     * 获取加载开始文字
     *
     * @return 文字内容
     */
    public String getLoadingText() {
        return header.getHeaderLodingStr();
    }

    /**
     * 设置加载结束文字
     *
     * @param loadingFinishedText 文字内容
     */
    public void setLoadingFinishedText(String loadingFinishedText) {
        if (isEmptyByText(loadingFinishedText)) {
            return;
        }
        header.setHeaderLoadingFinishedStr(loadingFinishedText);
    }

    /**
     * 获取加载结束文字
     *
     * @return 文字内容
     */
    public String getLoadingFinishedText() {
        return header.getHeaderLoadingFinishedStr();
    }


    /**
     * 设置游戏结束文字
     *
     * @param gameOverText 文字内容
     */
    public void setGameOverText(String gameOverText) {
        if (isEmptyByText(gameOverText)) {
            return;
        }
        header.setHeaderGameOverStr(gameOverText);
    }

    /**
     * 获取游戏结束文字
     *
     * @return 文字内容
     */
    public String getGameOverText() {
        return header.getHeaderGameOverStr();
    }


    /**
     * 设置上边帷幕中的文字
     *
     * @param topMaskText 文字内容
     */
    public void setTopMaskText(String topMaskText) {
        if (isEmptyByText(topMaskText)) {
            return;
        }
        header.setTopMaskViewText(topMaskText);
    }


    /**
     * 设置下边帷幕中的文字
     *
     * @param bottomMaskText 文字内容
     */
    public void setBottomMaskText(String bottomMaskText) {
        if (isEmptyByText(bottomMaskText)) {
            return;
        }
        header.setBottomMaskViewText(bottomMaskText);
    }

    /**
     * 获取游戏状态
     * @return 游戏状态
     */
    public int getGameStatus(){
        return header.getGameStatus();
    }


    private boolean isEmptyByText(String text) {
        return text == null || text.equals("");
    }


    /**
     * 下拉刷新的监听器，使用下拉刷新的地方应该注册此监听器来获取刷新回调。
     */
    public interface FunGameRefreshListener {
        /**
         * 刷新时回调方法
         */
        void onPullRefreshing();

        void onRefreshComplete();
    }
}
